//****************************************/
//* mElements  12 2011                   */
//* Riku Maikola rpm@ac-mapa.org         */
//****************************************/

#include "../mElements.h"


mPoint eLine::p1()
{
    return at(0);
};
mPoint eLine::p2()
{
    return at(1);
};

//********************************************************************************************************//
//**                //\\    element boxing  13.12.2012
//**               //__\\
//**              //    \\
//********************************************************************************************************//
void eLine::cArea()
{
    ClearArea();

    test(p1());
    test(p2());
}

//***********************************************************************************//
//**                                                                               **//
//***********************************************************************************//
bool eLine::Match(element ee)
{
    if( p1().Match(ee.p1()) && p2().Match(ee.p2()) && cp().Match(ee.cp()))return true;
    if( p1().Match(ee.p2()) && p2().Match(ee.p1()) && cp().Match(ee.cp()))return true;
    return false;
}
bool eLine::Match(eLine ci)
{
    if( p1().Match(ci.p1()) && p2().Match(ci.p2()))return true;
    if( p1().Match(ci.p2()) && p2().Match(ci.p1()))return true;
    return false;
}
//***********************************************************************************//
//**                                                                               **//
//**          get readbl data                         18.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
wxString eLine::Info()
{
    return wxString::Format( _("line p1()(%1.3f,%1.3f) p2()(%1.3f,%1.3f)"),p1().x, p1().y , p2().x , p2().y);
}

//***********************************************************************************//
//**                                                                               **//
//**          Connection  jump                       13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
bool eLine::Connection(mPoint *point,mPoint *center,int *type)
{
    if(p1().Match(*point))
    {
        point->SetValue(p2());
        center->SetValue(cp());
        *type = 1;
        return true;
    }
    if(p2().Match(*point))
    {
        point->SetValue(p1());
        center->SetValue(cp());
        *type = 1;
        return true;
    }
    return false;
}
//***********************************************************************************//
//**                                                                               **//
//**          get Distance from xy location          13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
double eLine::Distance(double X,double Y)
{
    double A = X - p1().x;
    double B = Y - p1().y;
    double C = p2().x - p1().x;
    double D = p2().y - p1().y;

    double dot = A * C + B * D;
    double len_sq = C * C + D * D;
    double param = dot / len_sq;

    double xi,yi;

    if (param < 0)
    {
        xi=p1().x;
        yi=p1().y;
    }
    else if (param > 1)
    {
        xi=p2().x;
        yi=p2().y;
    }
    else
    {
        xi = p1().x + param * C;
        yi = p1().y + param * D;
    }

    return Distance2D(X,Y,xi,yi);
}
//***********************************************************************************//
//**                                                                               **//
//**          INTERSECTION FOR LINE      18.2.2013                                 **//
//**                                                                               **//
//***********************************************************************************//
bool eLine::Intersection(mPointArray *A ,eLine line)
{
    mPointArray p;
    if( eR(p1(),p2()).Intersection(&p,eR(line.p1() , line.p2())))
    {
         if(Distance(p.at(0).x,p.at(0).y)<0.000001   &&   line.Distance(p.at(0).x,p.at(0).y)<0.000001)
         {
            A->Add(p.at(0),true);
            return true;
         }
    }
    return false;
}
bool eLine::Intersection(mPointArray *A, eArc arc)
{
    mPointArray p;
    bool answer = false;
    Intersection( &p, eC( arc.cp() , arc.r));
    for(uint a=0; a<p.size(); a++)
    {
        if(arc.Distance(p.at(a).x, p.at(a).y)<0.0000001)
        {
            A->Add(p.at(a),true);
            answer = true;
        }
    }
    return answer;
}
//******************** eLine **************************************//
bool eLine::Intersection(mPointArray *A,eCircle cir)
{
    mPointArray p;
    bool answer = false;

    if( cir.Intersection(&p,eR(p1(),p2())))
    {
        if(Distance(p.at(0).x,p.at(0).y)<0.00001)
        {
            A->Add(p.at(0),true);
            answer = true;
        }
        if(p.size()==2)
        {
            if(Distance(p.at(1).x,p.at(1).y)<0.00001)
            {
                A->Add(p.at(1),true);
                answer = true;
            }
        }
    }
    return answer;
}
bool eLine::Intersection(mPointArray *A,eRay ray)
{
    mPointArray p;
    if( eR(p1(),p2()).Intersection(&p,ray))
    {
         if(Distance(p.at(0).x,p.at(0).y)<0.000001)
         {
            A->Add(p.at(0),true);
            return true;
         }
    }
    return false;
}
//***************************//
//**
//**
//**
//***************************//
mPoint eLine::MidPoint()
{
    return p1().GetMidPoint(p2());
};

//*************************************//
bool eLine::Split(Image*I,mPoint point)
{
    if( Distance(point.x,point.y)>0.00001)
    {
        printf("eArc::Split() not in arc?\n");
        return false;
    }
    if(point.Match(p1()))return false;
    if(point.Match(p2()))return false;

    I->add(eL(point,p2()));
    p2()=point;

    return true;
}
//************************************************************************************************//
//**                                                                                            **//
//**                        ToArray                                                             **//
//**                                                                                            **//
//************************************************************************************************//
mPointArray eLine::ToArray(double accu)
{
    mPointArray A;
    if(direction)
    {
        A.Add(p1());
        A.Add(p2());
    }
    else
    {
        A.Add(p2());
        A.Add(p1());
    }
    return A;

}
//************************************************************************************************//
//**                                                                                            **//
//**                        GLOBAL..                                                            **//
//**                                                                                            **//
//************************************************************************************************//
eLine eL(mPoint p1 , mPoint p2,wxString L)
{
    eLine line;
//    line.layer=L;
    line.r = NAN;
    line.a1 = NAN;
    line.a2 = NAN;
    line.flag = false;
    line.push_back( p1 );
    line.push_back( p2 );
    line.push_back( mP(NAN,NAN,NAN) );

    line.cArea();
    return line;
}
